package main

import "fmt"

// 假设你实现了开启和关闭电视机的功能，随着业务迭代，
// 还需要实现开启和关闭冰箱的功能，开启和关闭电灯的功能，
// 开启和关闭微波炉的功能……这些功能都基于你的基类，开启和关闭。
// 如果你之后对基类进行修改，很可能会影响到其他功能，这使项目变得不稳定了。
// 一个优秀的设计往往会关注于软件的分层与解耦，命令模式试图做到这样的结果：
// 让命令和对应功能解耦，并能根据不同的请求将其方法参数化

type button struct {
	command command
}

func (b *button) press() {
	b.command.execute()
}

type command interface {
	execute()
}
type onCommand struct {
	device device
}

func (c *onCommand) execute() {
	c.device.on()
}

type offCommand struct {
	device device
}

func (c *offCommand) execute() {
	c.device.off()
}

type device interface {
	on()
	off()
}
type tv struct{}

func (t *tv) on() {
	fmt.Println("truning tv on")
}
func (t *tv) off() {
	fmt.Println("truning tv off")
}

type airConditioner struct{}

func (a *airConditioner) on() {
	fmt.Println("truning airConditioner on")
}
func (a *airConditioner) off() {
	fmt.Println("truning airConditioner off")
}

func ExampleCommand() {
	Tv()
	AirConditioner()
}

func Tv() {
	tv := &tv{}
	onTvCommand := &onCommand{
		device: tv,
	}
	offTvCommand := &offCommand{
		device: tv,
	}
	onTvButton := &button{
		command: onTvCommand,
	}
	onTvButton.press()
	offTvButton := &button{
		command: offTvCommand,
	}
	offTvButton.press()
}

func AirConditioner() {
	airConditioner := &airConditioner{}
	onAirConditionerCommand := &onCommand{
		device: airConditioner,
	}
	offAirConditionerCommand := &offCommand{
		device: airConditioner,
	}
	onAirConditionerButton := &button{
		command: onAirConditionerCommand,
	}
	onAirConditionerButton.press()

	offAirConditionerButton := &button{
		command: offAirConditionerCommand,
	}
	offAirConditionerButton.press()
}
